﻿Option Explicit On

'*******************************************************************
' Program: xmlVisio
' Author: Albert E Edlund
' Date:
'
' Purpose:
' Working with visio drawing in an xml format
'
' Visio XSD downloads
' http://www.microsoft.com/download/en/details.aspx?id=23976
'
' msdn linqtoxml samples
' http://code.msdn.microsoft.com/LINQ-Sample-Queries-13a42a54/sourcecode?fileId=22789&pathId=521681129
'
' orgchart example
' http://visguy.com/vgforum/index.php?topic=2298
'
' datarecordset example
' http://visguy.com/vgforum/index.php?topic=2474
'
' bpmn drawing example used with permission from Scott A. Helmers
' author of “Microsoft Visio 2010 Step by Step"
' http://www.visiostepbystep.com/
'
' Chris Roth's new book
' "Using Microsoft Visio 2010 "
' http://www.amazon.com/gp/product/0789742977/ref=as_li_ss_tl?ie=UTF8&tag=wanderkind-20&linkCode=as2&camp=217145&creative=399349&creativeASIN=0789742977
'
' Chris' xml presentation at developers conference
' http://www.visguy.com/2006/11/30/visio-and-xml-conference-resources/
'
' David Parker's book on bpmn
' "Microsoft Visio 2010 Business Process Diagramming and Validation" 
' http://www.amazon.com/s/ref=nb_sb_noss?url=search-alias%3Dstripbooks&field-keywords=david+parker+bpmn
'
'*******************************************************************



Imports System.Runtime.InteropServices
Imports Microsoft.Office.Interop
Imports Microsoft.Office.Interop.Visio


Imports System
Imports System.Collections.Generic
Imports System.Collections.ObjectModel
Imports System.Text
Imports System.Text.StringBuilder

Imports Microsoft.Practices.EnterpriseLibrary.Common
Imports Microsoft.Practices.EnterpriseLibrary.Data
Imports Microsoft.Practices.EnterpriseLibrary.ExceptionHandling
Imports Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging

Imports System.IO
Imports System.Windows.Forms
Imports System.Xml
Imports System.Xml.Serialization
Imports System.Xml.Linq
Imports System.Xml.XPath

Imports <xmlns="http://schemas.microsoft.com/visio/2003/core">
Imports <xmlns:vx="http://schemas.microsoft.com/visio/2006/extension">
Imports <xmlns:v14="http://schemas.microsoft.com/office/visio/2010/extension">

Imports ADODB
Imports System.Data
Imports System.Data.OleDb
Imports System.Data.Sql

Public Class frmMain


#Region " Properties and declarations "

    Public ReadOnly dataPath As String = System.IO.Path.GetFullPath(System.Windows.Forms.Application.StartupPath & "\..\..\Drawings\")

    '********* visio snippet vb.net visXXXX ******************
    Private _drawingApplication As Microsoft.Office.Interop.Visio.Application
    Public Property drawingApplication() As Microsoft.Office.Interop.Visio.Application
        Get
            Return Me._drawingApplication
        End Get
        Set(ByVal value As Microsoft.Office.Interop.Visio.Application)
            If (value Is Nothing) Then
                Throw New System.ArgumentNullException("Value", _
                    "drawingApplication is Null.")
            End If
            Me._drawingApplication = value
        End Set
    End Property


    '********* visio snippet vb.net visXXXX ******************
    Private _drawingDocument As Microsoft.Office.Interop.Visio.Document
    Public Property drawingDocument() As Microsoft.Office.Interop.Visio.Document
        Get
            Return Me._drawingDocument
        End Get
        Set(ByVal value As Microsoft.Office.Interop.Visio.Document)
            If (value Is Nothing) Then
                Throw New System.ArgumentNullException("Value", _
                    "drawingDocument is Null.")
            End If
            Me._drawingDocument = value
        End Set
    End Property


    '********* visio snippet vb.net visXXXX ******************
    Private _drawingWindow As Microsoft.Office.Interop.Visio.Window
    Public Property drawingWindow() As Microsoft.Office.Interop.Visio.Window
        Get
            Return Me._drawingWindow
        End Get
        Set(ByVal value As Microsoft.Office.Interop.Visio.Window)
            If (value Is Nothing) Then
                Throw New System.ArgumentNullException("Value", _
                    "drawingWindow is Null.")
            End If
            Me._drawingWindow = value
        End Set
    End Property

    '********* visio snippet vb.net visXXXX ******************
    Private _drawingPage As Microsoft.Office.Interop.Visio.Page
    Public Property drawingPage() As Microsoft.Office.Interop.Visio.Page
        Get
            Return Me._drawingPage
        End Get
        Set(ByVal value As Microsoft.Office.Interop.Visio.Page)
            If (value Is Nothing) Then
                Throw New System.ArgumentNullException("Value", _
                    "drawingPage is Null.")
            End If
            Me._drawingPage = value
        End Set
    End Property


    '********* visio snippet vb.net visXXXX ******************
    Private _drawingControl As AxMicrosoft.Office.Interop.VisOcx.AxDrawingControl
    Public Property drawingControl() As AxMicrosoft.Office.Interop.VisOcx.AxDrawingControl
        Get
            Return Me._drawingControl
        End Get
        Set(ByVal value As AxMicrosoft.Office.Interop.VisOcx.AxDrawingControl)
            Me._drawingControl = value
        End Set
    End Property


    Public _xDoc As XDocument
    Public Property xDoc As XDocument
        Get
            Return Me._xDoc
        End Get
        Set(value As XDocument)
            If (value Is Nothing) Then
                Throw New System.ArgumentNullException("Value", _
                    "xDoc is Null.")
            End If
            Me._xDoc = value
        End Set
    End Property

    Private _nsDict As Dictionary(Of String, System.Xml.Linq.XNamespace)
    Public Property nsDict As Dictionary(Of String, System.Xml.Linq.XNamespace)
        Get
            Return Me._nsDict
        End Get
        Set(value As Dictionary(Of String, System.Xml.Linq.XNamespace))
            If (value Is Nothing) Then
                Throw New System.ArgumentNullException("Value", _
                    "nsDict is Null.")
            End If
            Me._nsDict = value
        End Set
    End Property

    


#End Region


#Region " LinqToXml "

    Public Function ElementsAnyNS(Of T As XContainer)(source As IEnumerable(Of T), localName As String) As IEnumerable(Of XElement)
        Return source.Elements().Where(Function(e) e.Name.LocalName = localName)
    End Function

    '
    '
    '
    Private Sub SaveToolStripMenuItem_Click(sender As Object, e As System.EventArgs) Handles SaveToolStripMenuItem.Click
        Try
            FutureFeature()
        Catch NotImp As NotImplementedException
            MsgBox(NotImp.Message)
        End Try

    End Sub



#End Region

    '
    '
    '
    Private Function openVDX_File() As XDocument

        Dim document As XmlDocument
        document = New XmlDocument


        Try

            Me.txtFileName.Text = ""

            OpenFileDialog.InitialDirectory = dataPath
            OpenFileDialog.FileName = "*.vdx"
            OpenFileDialog.Filter = "visio drawings (*.vdx)|*.vsd|All files (*.*)|*.*"
            OpenFileDialog.FilterIndex = 1
            OpenFileDialog.RestoreDirectory = True

            Dim strPath As String = ""
            Dim dlgResult As System.Windows.Forms.DialogResult = OpenFileDialog.ShowDialog

            If dlgResult = System.Windows.Forms.DialogResult.OK Then

                Me.txtFileName.Text = OpenFileDialog.FileName
                System.Windows.Forms.Application.DoEvents()

                xDoc = XDocument.Load(Me.txtFileName.Text)

                ' load the namespace dictionary
                Dim xdocWork As XDocument = XDocument.Parse(Me.xDoc.ToString)
                Dim dictResult = xdocWork.Root.Attributes(). _
                    Where(Function(a) a.IsNamespaceDeclaration). _
                    GroupBy(Function(a) If(a.Name.[Namespace] = XNamespace.None, [String].Empty, a.Name.LocalName), Function(a) XNamespace.[Get](a.Value)). _
                    ToDictionary(Function(g) g.Key, Function(g) g.First())

                Me.nsDict = dictResult

            End If ' file name read

        Catch err As Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(err, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        End Try



        Return xDoc

    End Function


    '
    ' throw not implemented exception
    '
    Private Sub FutureFeature()
        Throw New NotImplementedException
    End Sub


    '
    '
    '
    Private Sub ExitToolStripMenuItem_Click(sender As Object, e As System.EventArgs) Handles ExitToolStripMenuItem.Click
        Me.Close()
    End Sub

    '
    '
    '
    Public Sub New()

        ' This call is required by the designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.

        _drawingApplication = Nothing
        _drawingDocument = Nothing
        _drawingPage = Nothing

        drawingControl = AxDrawingControl1
        ' get the environment data from the drawing control
        InitTheDrawingControl()


        txtXML.Text = ""
        txtFileName.Text = "c:\applications\xmlVisio\xmlVisio\Drawings\vbaAppConnect.vdx"

        Me._xDoc = Nothing


    End Sub


#Region " Display drawing buttons "

#Region " xml treeview "


    '
    '
    '
    Private Sub TreeviewToolStripMenuItem_Click(sender As System.Object, e As System.EventArgs) Handles TreeviewToolStripMenuItem.Click

        openTreeview()

    End Sub

    '
    ' isolate the call so that I can chain the views together
    '
    Private Sub openTreeview()
        Try


            If xDoc Is Nothing Then
                openVDX_File()
            End If

            createTreeFromXml(xDoc.ToString)

            Me.TabControl1.SelectTab(tabTree)



        Catch com As COMException
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(com, "Com+ Policy")
            If (rethrow) Then
                Throw
            End If
        Catch err As Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(err, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        End Try



        Status1.Text = ""
    End Sub


    '
    '
    '
    Private Sub createTreeFromXml(ByVal strDoc As String)



        Try

            TreeView1.Nodes.Clear()

            Status1.Text = "Reading Document"
            System.Windows.Forms.Application.DoEvents()

            'load the XMl file   
            'loop through the top nodes  
            Status1.Text = " Doc Loaded, Analyze XML "
            System.Windows.Forms.Application.DoEvents()

            Dim newDoc As XmlDocument = New XmlDocument
            newDoc.LoadXml(strDoc)

            For Each node As XmlNode In newDoc
                Dim treeNode As TreeNode = createTreeNode(node)
                GetAttributes(node, treeNode)
                treeNode.Text = FormatName(node)
                TreeView1.Nodes.Add(treeNode)
            Next

            Status1.Text = " Drawing Tree "
            System.Windows.Forms.Application.DoEvents()

            'TreeView1.ExpandAll()

            Me.Cursor = Cursors.Default
            Status1.Text = " Tree Draw Complete"

        Catch err As XmlException
            Dim sbErr As StringBuilder = New StringBuilder
            sbErr.AppendLine(err.Message)
            sbErr.AppendLine(("Exception object Line, pos: (" & err.LineNumber & "," & err.LinePosition & ")"))
            sbErr.AppendLine("Exception source URI: (" + err.SourceUri + ")")
            MsgBox(sbErr.ToString)
        Catch err As Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(err, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        End Try

        Status1.Text = ""



    End Sub

    '
    '
    '
    Private Function createTreeNode(parentNode As XmlNode) As TreeNode
        Dim treeNode As New TreeNode()

        For Each childNode As XmlNode In parentNode.ChildNodes
            If childNode.NodeType = XmlNodeType.Element Then
                Dim childTreeNode As New TreeNode()

                If childNode.ChildNodes.Count > 0 Then
                    childTreeNode = createTreeNode(childNode)
                End If

                childTreeNode.Text = FormatName(childNode)
                GetAttributes(childNode, childTreeNode)
                treeNode.Nodes.Add(childTreeNode)
            End If
        Next

        Return treeNode

    End Function

    '
    '
    '
    Private Function FormatName(node As XmlNode) As String
        Dim fullName As String = "<" & Convert.ToString(node.Name)

        If node.InnerText <> "" Then
            fullName += ">" & Convert.ToString(node.InnerText) & "</" & Convert.ToString(node.Name) & ">"
        Else
            fullName += ">"
        End If

        Return fullName
    End Function

    '
    '
    '
    Private Sub GetAttributes(node As XmlNode, treeNode As TreeNode)

        If node.Attributes IsNot Nothing Then
            Dim attributes As ListViewItem() = New ListViewItem(node.Attributes.Count - 1) {}

            For i As Integer = 0 To node.Attributes.Count - 1
                attributes(i) = New ListViewItem(New String() {node.Attributes(i).Name, node.Attributes(i).Value})
            Next

            treeNode.Tag = attributes
        End If
    End Sub

#End Region


#Region " xml text "

    '
    '
    '
    Private Sub TextFileToolStripMenuItem_Click(sender As System.Object, e As System.EventArgs) Handles TextFileToolStripMenuItem.Click

        If xDoc Is Nothing Then
            openVDX_File()
        End If

        CreateTextFromXML()


    End Sub

    '
    ' open the vdx file with an xmltextreader
    '
    Private Sub CreateTextFromXML()


        Try

            Dim strDoc As String = xDoc.ToString
            txtXML.Text = strDoc

            Me.TabControl1.SelectTab(tabText)

        Catch ex As Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(ex, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If

        End Try


    End Sub 'Main ' End class


#End Region


#Region " Visio Drawing Control "


    '
    '
    '
    Private Sub VisioDrawingToolStripMenuItem_Click(sender As System.Object, e As System.EventArgs) Handles VisioDrawingToolStripMenuItem.Click

        openVisioDrawing()

    End Sub

    '
    '
    '
    Private Sub openVisioDrawing()
        Try

            If xDoc Is Nothing Then
                openVDX_File()
            End If

            If Me.txtFileName.Text <> "" Then

                Me.drawingControl.Src = Me.txtFileName.Text

                Me.drawingWindow = Me.drawingControl.Window
                Me.drawingApplication = Me.drawingControl.Window.Application
                Me.drawingDocument = Me.drawingApplication.ActiveDocument
                Me.drawingPage = Me.drawingApplication.ActivePage

                ' flag it as already having been saved
                Me.drawingDocument.Saved = True

            End If


            Me.TabControl1.SelectTab(tabVisio)

        Catch com As COMException
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(com, "Com+ Policy")
            If (rethrow) Then
                Throw
            End If
        Catch err As Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(err, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        End Try
    End Sub

    '********* visio snippet vb.net vis0049vb ******************
    ' Properties and Definitions
    Private Const defaultDocumentName As String = "vdxTest"
    Private Const defaultPageName As String = "vdxTest"

    '
    '
    '
    Private Sub InitTheDrawingControl()

        Try

            '
            ' get the pointers
            '
            ' make sure the control does not change the pagesizebehavior
            Me.drawingControl.PageSizingBehavior = VisPageSizingBehaviors.visNeverResizePages

            Me.drawingWindow = Me.drawingControl.Window
            Me.drawingWindow.Activate()
            Me.drawingApplication = Me.drawingControl.Window.Application

            Me.drawingDocument = Me.drawingControl.Document
            Dim docSheet As Shape = Me.drawingDocument.DocumentSheet
            docSheet.NameU = defaultDocumentName
            Me.drawingDocument.DiagramServicesEnabled = VisDiagramServices.visServiceVersion140

            Me.drawingPage = Me.drawingControl.Window.Page
            Me.drawingPage.NameU = defaultPageName
            drawingWindow.Page = drawingPage

            Me.drawingApplication.Application.Settings.EnableAutoConnect = False
            Me.drawingApplication.OnDataChangeDelay = -2

            Me.drawingWindow.ShowGrid = False
            Me.drawingWindow.ShowPageTabs = True
            Me.drawingWindow.ShowRulers = False
            Me.drawingWindow.ShowScrollBars = True


        Catch com As COMException
            ' add com exception handler here
            '********* visio snippet vb.net vis0056vb ******************
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(com, "Com+ Policy")
            If (rethrow) Then
                Throw
            End If

        Catch ex As Exception
            ' add exception handler here
            '********* visio snippet vb.net vis0059vb ******************
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(ex, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        End Try

    End Sub

    

#End Region

#End Region



    '
    ' about dialog 
    '
    Private Sub AboutToolStripMenuItem_Click(sender As System.Object, e As System.EventArgs) Handles AboutToolStripMenuItem.Click
        frmAbout.ShowDialog()
    End Sub

    '
    ' open vdx file
    '
    Private Sub OpenToolStripMenuItem_Click(sender As System.Object, e As System.EventArgs) Handles OpenToolStripMenuItem.Click

        ' clear whatever may be loaded
        _xDoc = Nothing

        ' get the new file
        openVDX_File()

        Me.Cursor = Cursors.WaitCursor

        openTreeview()

        CreateTextFromXML()

        openVisioDrawing()

        Me.Cursor = Cursors.Default

    End Sub

    '
    ' open up the pageshapes form
    '
    Private Sub ShapesToolStripMenuItem_Click(sender As System.Object, e As System.EventArgs) Handles ShapesToolStripMenuItem.Click

        If xDoc Is Nothing Then
            openVDX_File()
        End If

        frmPageShapes.dataPath = Me.dataPath
        frmPageShapes.xDoc = Me.xDoc
        frmPageShapes.getPages(Nothing)
        frmPageShapes.ShowDialog()

    End Sub

    '
    ' open the pageconnections form
    '
    Private Sub ConnectionsToolStripMenuItem_Click(sender As Object, e As System.EventArgs) Handles ConnectionsToolStripMenuItem.Click
        If xDoc Is Nothing Then
            openVDX_File()
        End If

        frmPageConnections.dataPath = Me.dataPath
        frmPageConnections.xDoc = Me.xDoc
        frmPageConnections.buildPageShapeDict()
        frmPageConnections.getMasters()
        frmPageConnections.getPages(Nothing)
        frmPageConnections.ShowDialog()

    End Sub


    '
    ' external data cache
    '
    Private Sub AdoDataToolStripMenuItem_Click(sender As Object, e As System.EventArgs) Handles AdoDataToolStripMenuItem.Click
        If xDoc Is Nothing Then
            openVDX_File()
        End If

        frmAdoData.dataPath = Me.dataPath
        frmAdoData.xDoc = Me.xDoc
        frmAdoData.ShowDialog()

    End Sub


    '
    ' columns and rowmapping
    '
    Private Sub DataMappingToolStripMenuItem_Click(sender As Object, e As System.EventArgs) Handles DataMappingToolStripMenuItem.Click

        If xDoc Is Nothing Then
            openVDX_File()
        End If

        frmDataMapping.dataPath = Me.dataPath
        frmDataMapping.xDoc = Me.xDoc
        frmDataMapping.buildPageShapeDict()
        frmDataMapping.getDataRecordSets(Nothing)
        frmDataMapping.ShowDialog()

    End Sub

    '
    ' validation rule sets
    '
    Private Sub RuleSetsToolStripMenuItem_Click(sender As System.Object, e As System.EventArgs) Handles RuleSetsToolStripMenuItem.Click

        If xDoc Is Nothing Then
            openVDX_File()
        End If

        frmRuleSets.dataPath = Me.dataPath
        frmRuleSets.xDoc = Me.xDoc
        frmRuleSets.getRuleSets(Nothing)
        frmRuleSets.ShowDialog()

    End Sub

    '
    ' validation issues
    '
    Private Sub IssuesToolStripMenuItem_Click(sender As System.Object, e As System.EventArgs) Handles IssuesToolStripMenuItem.Click
        If xDoc Is Nothing Then
            openVDX_File()
        End If

        frmRuleIssues.dataPath = Me.dataPath
        frmRuleIssues.xDoc = Me.xDoc

        frmRuleIssues.buildPageShapeDict()

        frmRuleIssues.getRuleIssues(Nothing)
        frmRuleIssues.ShowDialog()

    End Sub


    '
    '
    '
    Private Sub DocInfoToolStripMenuItem_Click(sender As System.Object, e As System.EventArgs) Handles DocInfoToolStripMenuItem.Click

        If xDoc Is Nothing Then
            openVDX_File()
        End If

        frmDocument.dataPath = Me.dataPath
        frmDocument.xDoc = Me.xDoc

        frmDocument.getDocProperties()
        frmDocument.getEvents(Nothing)

        frmDocument.ShowDialog()

    End Sub

End Class
